import asyncio
import tkinter as tk
from tkinter import scrolledtext, filedialog, messagebox
import threading
import os
from .base_client import BaseChatClient


class GUIClient(BaseChatClient):
    """GUI聊天客户端"""

    def __init__(self, config_file=None):
        super().__init__(config_file)
        self.users = []

        # 创建GUI
        self.root = tk.Tk()
        self.root.title("IM聊天客户端")
        self.root.geometry("600x500")
        self.root.protocol("WM_DELETE_WINDOW", self._on_closing)

        # 创建登录界面
        self.login_frame = tk.Frame(self.root)
        self.login_frame.pack(fill=tk.BOTH, expand=True)

        tk.Label(self.login_frame, text="服务器地址:").grid(row=0, column=0, padx=10, pady=5, sticky=tk.W)
        self.server_entry = tk.Entry(self.login_frame)
        self.server_entry.grid(row=0, column=1, padx=10, pady=5)
        self.server_entry.insert(0, "ws://localhost:18229")

        tk.Label(self.login_frame, text="用户ID:").grid(row=1, column=0, padx=10, pady=5, sticky=tk.W)
        self.user_id_entry = tk.Entry(self.login_frame)
        self.user_id_entry.grid(row=1, column=1, padx=10, pady=5)

        # 移除用户名输入框，因为我们只使用用户ID
        # 用户名标签和输入框已移除
        pass

        tk.Label(self.login_frame, text="房间ID:").grid(row=3, column=0, padx=10, pady=5, sticky=tk.W)
        self.room_entry = tk.Entry(self.login_frame)
        self.room_entry.grid(row=3, column=1, padx=10, pady=5)
        self.room_entry.insert(0, "default")

        self.login_button = tk.Button(self.login_frame, text="连接", command=self._connect_wrapper)
        self.login_button.grid(row=4, column=1, padx=10, pady=10)

        # 创建聊天界面（初始隐藏）
        self.chat_frame = tk.Frame(self.root)

        # 用户列表
        self.user_list_frame = tk.Frame(self.chat_frame)
        self.user_list_frame.pack(side=tk.RIGHT, fill=tk.Y, padx=5, pady=5)
        tk.Label(self.user_list_frame, text="在线用户").pack()
        self.user_listbox = tk.Listbox(self.user_list_frame, width=20)
        self.user_listbox.pack(fill=tk.BOTH, expand=True)

        # 消息显示区域
        self.message_frame = tk.Frame(self.chat_frame)
        self.message_frame.pack(side=tk.TOP, fill=tk.BOTH, expand=True, padx=5, pady=5)

        self.message_display = scrolledtext.ScrolledText(self.message_frame, state=tk.DISABLED)
        self.message_display.pack(fill=tk.BOTH, expand=True)

        # 消息输入区域
        self.input_frame = tk.Frame(self.chat_frame)
        self.input_frame.pack(side=tk.BOTTOM, fill=tk.X, padx=5, pady=5)

        self.message_entry = tk.Entry(self.input_frame)
        self.message_entry.pack(side=tk.LEFT, fill=tk.X, expand=True)
        self.message_entry.bind("<Return>", self._send_message_wrapper)

        self.send_button = tk.Button(self.input_frame, text="发送", command=self._send_message_wrapper)
        self.send_button.pack(side=tk.RIGHT, padx=(5,0))

        self.file_button = tk.Button(self.input_frame, text="发送文件", command=self._send_file_wrapper)
        self.file_button.pack(side=tk.RIGHT, padx=(5,0))

        self.disconnect_button = tk.Button(self.input_frame, text="断开连接", command=self._disconnect_wrapper)
        self.disconnect_button.pack(side=tk.RIGHT, padx=(5,0))

    def _connect_wrapper(self):
        """连接按钮事件处理"""
        server_address = self.server_entry.get().strip()
        user_id = self.user_id_entry.get().strip()
        room_id = self.room_entry.get().strip()

        # 验证输入
        if not all([server_address, user_id]):
            messagebox.showerror("错误", "服务器地址和用户ID不能为空！")
            return

        if not room_id:
            room_id = "default"

        # 在新线程中连接服务器
        threading.Thread(
            target=self._start_client,
            args=(server_address, user_id, room_id),
            daemon=True
        ).start()

    def _start_client(self, server_address, user_id, room_id):
        """启动客户端"""
        try:
            # 创建事件循环
            loop = asyncio.new_event_loop()
            asyncio.set_event_loop(loop)

            # 连接到服务器
            loop.run_until_complete(self.connect(server_address, user_id, room_id))
        except Exception as e:
            self.root.after(0, lambda: messagebox.showerror("连接错误", f"无法连接到服务器: {str(e)}"))

    def _send_message_wrapper(self, event=None):
        """发送消息事件处理"""
        message = self.message_entry.get()
        if message and self.is_connected:
            asyncio.create_task(self.send_text_message(message))

    def _send_file_wrapper(self):
        """发送文件事件处理"""
        if not self.is_connected:
            messagebox.showerror("错误", "未连接到服务器")
            return

        file_path = filedialog.askopenfilename()
        if file_path:
            asyncio.create_task(self.send_file(file_path))

    def _disconnect_wrapper(self):
        """断开连接事件处理"""
        asyncio.create_task(self.disconnect())

    def _on_closing(self):
        """窗口关闭事件处理"""
        if self.is_connected:
            asyncio.create_task(self.disconnect())
        self.root.destroy()

    # 实现抽象方法
    async def on_connected(self):
        """连接成功时调用"""
        self.root.after(0, self._switch_to_chat)

    async def on_disconnected(self):
        """断开连接时调用"""
        self.root.after(0, self._switch_to_login)
        self.root.after(0, lambda: self._show_message("与服务器的连接已断开", "System"))

    async def on_text_message_received(self, formatted_message, sender, raw_message):
        """收到文本消息时调用"""
        self.root.after(0, lambda: self._show_message(formatted_message, sender))

    async def on_file_received(self, file_data):
        """收到文件时调用"""
        sender = file_data['sender']
        filename = file_data['filename']
        filedata = file_data['filedata']
        timestamp = file_data['timestamp']

        # 在主线程中处理文件保存
        self.root.after(0, lambda: self._handle_incoming_file(sender, filename, filedata, timestamp))

    async def on_system_message_received(self, formatted_message, raw_message):
        """收到系统消息时调用"""
        self.root.after(0, lambda: self._show_message(formatted_message, "System"))

    async def on_user_list_updated(self, users):
        """用户列表更新时调用"""
        self.users = users
        self.root.after(0, self._update_user_list)

    async def on_message_sent(self, message):
        """消息发送成功时调用"""
        self.root.after(0, lambda: self.message_entry.delete(0, tk.END))

    async def on_file_sent(self, filename):
        """文件发送成功时调用"""
        self.root.after(0, lambda: self._show_message(f"文件 {filename} 已发送", "You"))

    async def on_error(self, error_message):
        """发生错误时调用"""
        self.root.after(0, lambda: messagebox.showerror("错误", error_message))

    def _switch_to_chat(self):
        """切换到聊天界面"""
        self.login_frame.pack_forget()
        self.chat_frame.pack(fill=tk.BOTH, expand=True)
        self.root.title(f"IM聊天客户端 - {self.user_id}@{self.room_id}")

    def _switch_to_login(self):
        """切换到登录界面"""
        self.chat_frame.pack_forget()
        self.login_frame.pack(fill=tk.BOTH, expand=True)
        self.root.title("IM聊天客户端")

    def _show_message(self, message, sender):
        """在消息显示区域显示消息"""
        # 如果sender是用户ID而不是用户名，保持原样显示
        self.message_display.config(state=tk.NORMAL)
        self.message_display.insert(tk.END, message + "\n")
        self.message_display.config(state=tk.DISABLED)
        self.message_display.see(tk.END)

    def _update_user_list(self):
        """更新用户列表"""
        self.user_listbox.delete(0, tk.END)
        for user in self.users:
            self.user_listbox.insert(tk.END, user)

    def _handle_incoming_file(self, sender, filename, filedata, timestamp):
        """处理接收到的文件"""
        # 保存文件
        save_path = filedialog.asksaveasfilename(
            initialfile=filename,
            title=f"保存来自用户 {sender} 的文件",
            filetypes=[("所有文件", "*.*")]
        )

        if save_path:
            try:
                # 解码并保存文件
                import base64
                file_bytes = base64.b64decode(filedata)
                with open(save_path, "wb") as f:
                    f.write(file_bytes)
                msg = f"[{timestamp}] 用户 {sender} 发送了一个文件: {filename} (已保存到 {save_path})"
                self._show_message(msg, sender)
            except Exception as e:
                msg = f"[{timestamp}] 用户 {sender} 发送的文件 {filename} 保存失败: {str(e)}"
                self._show_message(msg, sender)
        else:
            msg = f"[{timestamp}] 用户 {sender} 发送了一个文件: {filename} (已取消保存)"
            self._show_message(msg, sender)

    def run(self):
        """运行客户端"""
        self.root.mainloop()


if __name__ == "__main__":
    client = GUIClient()
    client.run()